#define BLINKER_PRINT Serial
#define BLINKER_WIFI
#define BLINKER_MIOT_OUTLET // 小爱同学


#include <Blinker.h>
#include <WiFiUdp.h>
#include <WakeOnLan.h>
#include <WiFiClientSecure.h>


// WOL 唤醒
WiFiUDP UDP;
WakeOnLan WOL(UDP);
// MAC 地址
const char* MAC_ADDRESS = "00:D8:61:7B:85:F4";

// 点灯相关配置
char auth[] = "点灯科技key";
char ssid[] = "wifi SSID";
char pswd[] = "wifi 密码";

// HTTP 请求相关
const char* HOST = "192.168.0.22";
const int PORT = 8080;
const String BASE_URL = "/computer-manager/manager/";

// wol 按钮组件
BlinkerButton BUTTON_WOL("btn-wol");
// 关机 按钮组件
BlinkerButton BUTTON_SHUTDOWN("btn-shutdown");
// 重启 按钮组件
BlinkerButton BUTTON_RESTART("btn-restart");
// 撤销 按钮组件
BlinkerButton BUTTON_CANCEL("btn-cancel");
// 状态展示 按钮
BlinkerButton BUTTON_STATUS("btn-status");
// 状态
bool onState = false;

// 心跳包函数, 上报状态
void heartbeat() {
  btnStatusCallback(BLINKER_CMD_BUTTON_TAP);
}

// 小爱同学控制方法
void miotPowerState(const String & state) {
  BLINKER_LOG("miotPowerState state: ", state);

  //小爱同学控制开命令
  if (state == BLINKER_CMD_ON) {
    btnWolCallback(BLINKER_CMD_BUTTON_TAP);
  } else if (state == BLINKER_CMD_OFF) {
    //小爱同学控制关命令
    btnShutdownCallback(BLINKER_CMD_BUTTON_TAP);
  }
}

// 小爱同学查询方法
void miotQuery(int32_t queryCode){
  BLINKER_LOG("miotQuery codes: ", queryCode);

  switch (queryCode) {
    case BLINKER_CMD_QUERY_ALL_NUMBER :
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
      updateMiotState();
      break;
    default :
      updateMiotState();
  }
}


// wol唤醒
void btnWolCallback(const String & state) {
  BLINKER_LOG("btnWolCallback enter: ", state);
  // 点击按钮, 调用 wol 方法
  if (state == BLINKER_CMD_BUTTON_TAP) {
    wakeOnLan();
    onState = true;
    updateMiotState();
    updateBlinkerState();
  }
}

// shutdown
void btnShutdownCallback(const String & state) {
  BLINKER_LOG("btnShutdownCallback enter: ", state);
  // 点击按钮, 请求 shutdown 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String result = post("shutdown");
    if (result == "0") {
      BLINKER_LOG("shutdown success !");
      onState = false;
    } else {
      BLINKER_LOG("shutdown fail...");
    }
    updateMiotState();
    updateBlinkerState();
  }
}

// restart
void btnRestartCallback(const String & state) {
  BLINKER_LOG("btnRestartCallback enter: ", state);
  // 点击按钮, 请求 restart 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String result = post("restart");
    if (result == "0") {
      BLINKER_LOG("restart success !");
    } else {
      BLINKER_LOG("restart fail...");
    }
  }
}

// cancel
void btnCancelCallback(const String & state) {
  BLINKER_LOG("btnCancelCallback enter: ", state);
  // 点击按钮, 请求 cancel 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String result = post("cancel");
    if (result == "0") {
      BLINKER_LOG("cancel success !");
    } else {
      BLINKER_LOG("cancel fail...");
    }
    btnStatusCallback(BLINKER_CMD_BUTTON_TAP);
  }
}

// status
void btnStatusCallback(const String & state) {
  BLINKER_LOG("btnStatusCallback enter: ", state);
  // 点击按钮, 请求 echo 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String rand_str = (String) random(100);
    String result = post("echo?msg=" + rand_str);
    if (result == rand_str) {
      BLINKER_LOG("echo success !");

      onState = true;
    } else {
      BLINKER_LOG("echo fail...");

      onState = false;
    }
    // 刷新小爱接口状态
    updateMiotState();
    // 刷新点灯app中的状态
    updateBlinkerState();
  }
}

// 更新状态显示的方法
void updateBlinkerState() {
    BLINKER_LOG("updateBlinkerState: ", onState);

    String color;
    String text;
    String icon;

    if (onState) {
       color = "#3CB371";
       text = "online";
       icon = "fa fa-server";
    } else {
       color = "#A9A9A9";
       text = "offline";
       icon = "fa fa-server";
    }

    // 刷新点灯 app 状态
    BUTTON_STATUS.color(color);
    BUTTON_STATUS.text(text);
    BUTTON_STATUS.icon(icon);
    BUTTON_STATUS.print();
}

// 返回给小爱同学的状态
void updateMiotState() {
    BLINKER_LOG("updateMiotState: ", onState);

    String miotState = onState?"on":"off";
    // 更新小爱同学状态
    BlinkerMIOT.powerState(miotState);
    BlinkerMIOT.print();
}

// 如果未绑定的组件被触发，则会执行其中内容
void dataRead(const String & data) {
  BLINKER_LOG("Blinker dataRead: ", data);
}

void wakeOnLan() {
  // 发送 WOL 数据包
  WOL.sendMagicPacket(MAC_ADDRESS);
  BLINKER_LOG("wakeOnLan finish...");
}

String post(String url) {
  BLINKER_LOG("http post: ", BASE_URL + url);
  WiFiClient client;
  client.setTimeout(500);

  BLINKER_LOG("Http Connecting...");
  // 尝试连接服务器并等待
  int r = 0;
  while ((!client.connect(HOST, PORT)) && (r < 3)) {
    r ++;
    delay(100);
  }
  // 连接超时后输出"连接失败"信息并返回
  if (r == 3) {
    BLINKER_LOG("Http Connection Failed...");
    return "-1";
  } else {
    // 连接成功则输出“连接成功”信息
    BLINKER_LOG("Http Connected...");
  }

  String postRequest = (String)("POST ") + BASE_URL + url + " HTTP/1.1\r\n" +
                       "Host: " + HOST + "\r\n" +
                       "Connection: close\r\n\r\n";
  client.print(postRequest);
  // 使用find跳过HTTP响应头
  if (client.find("\r\n\r\n")) {
    BLINKER_LOG("Found Header End...");
  }
  String result = client.readStringUntil('\n');
  BLINKER_LOG("Http Post Result: ", result);
  client.stop();

  return result;
}

void setup() {
  // 初始化串口
  Serial.begin(9600);
  BLINKER_DEBUG.stream(Serial);

  // 初始化blinker
  Blinker.begin(auth, ssid, pswd);
  Blinker.attachData(dataRead);

  BlinkerMIOT.attachPowerState(miotPowerState);
  BlinkerMIOT.attachQuery(miotQuery);

  BUTTON_WOL.attach(btnWolCallback);
  BUTTON_SHUTDOWN.attach(btnShutdownCallback);
  BUTTON_RESTART.attach(btnRestartCallback);
  BUTTON_CANCEL.attach(btnCancelCallback);
  BUTTON_STATUS.attach(btnStatusCallback);
}

void loop() {
  Blinker.run();
}
